package com.study.mike.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.study.mike.common.enums.BizCodeEnum;
import com.study.mike.common.exception.BizException;
import com.study.mike.mapper.ResourceMapper;
import com.study.mike.mapper.UserRoleMapper;
import com.study.mike.model.dto.QueryUserRoleDTO;
import com.study.mike.model.dto.UserResourceNameDTO;
import com.study.mike.model.entity.ResourceDO;
import com.study.mike.model.entity.UserRole;
import com.study.mike.model.dto.UserRoleDTO;
import com.study.mike.model.po.*;
import com.study.mike.service.ResourceService;
import com.study.mike.service.UserRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author KangHui
 * @Date 2022/8/5 15:47
 */
@Service
@Slf4j
public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> implements UserRoleService {
    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private ResourceMapper resourceMapper;
    @Resource
    private ResourceService resourceService;


    @Override
    public List<UserRoleDTO> getUserRoles(GetUserRolePO po) {
        List<UserRoleDTO> resourceDOS = userRoleMapper.query(po);
        return resourceDOS;
    }

    @Override
    public List<String> getResource(GetUserRolePO po) {
        List<ResourceDO> resourceDOS = resourceMapper.queryResource(po);
        List<Long> ids = resourceDOS.stream().map(item -> item.getId()).distinct().collect(Collectors.toList());
        List<String> resourceName = resourceMapper.selectBatchIds(ids).stream().map(item -> item.getName()).collect(Collectors.toList());
        return resourceName;
    }

    @Override
    public List<String> getResourceName(GetUserRolePO po) {
        List<UserResourceNameDTO> resourceNames = resourceMapper.queryResourceName(po);
        // 按照id从小到大排序，将资源名单独封装为list返回
        List<String> names = resourceNames.stream().sorted(Comparator.comparing(UserResourceNameDTO::getId)).map(item -> item.getName()).collect(Collectors.toList());
        return names;
    }

    @Override
    public List<String> getResourceNameASC(GetUserRolePO po) {
        // 获取数据
        List<UserResourceNameDTO> resourceNames = resourceMapper.queryResourceName(po);
        // 封装返回资源名
        List<String> names = resourceNames.stream().map(item -> item.getName()).collect(Collectors.toList());
        return names;
    }

    @Override
    public List<QueryUserRoleDTO> treeInfo(GetUserRolePO po) {
        List<QueryUserRoleDTO> resourceDTOS = userRoleMapper.userRoleList(po);
       return resourceDTOS;
    }

    @Override
    public Boolean grantUserResources(GrantUserResourcesPO po) {
        return null;
    }

//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public Boolean grantUserResources(GrantUserResourcesPO po) {
//        //01、做用户是否拥有资源的验证
//        // 待新增的资源列表
//        List<Integer> resources = po.getResources();
//        List<UserRole> userRoleDTOS = new ArrayList<>();
//        for (Integer integer : resources) {
//            // 02、根据用户id、资源id检索用户资源数据
//            if (findResource(po.getUserId(), integer) > 0) {
//                continue;
//            }
//            UserRole userRole = new UserRole();
//            userRole.setUserId(po.getUserId());
//            userRole.setResourceId(integer);
//            userRole.setEnable(1);
//            userRoleDTOS.add(userRole);
//        }
//        // 写入数据：userResource
//        try {
//            return this.saveBatch(userRoleDTOS);
//        } catch (Exception e) {
//            // 手动处理异常
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            log.info("新增资源异常");
//            return false;
//        }
//
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResourceDO addResource(AddResourcePO po) {
        // 验证资源名是否重复
        LambdaQueryWrapper<ResourceDO> wrapper = new LambdaQueryWrapper();
        wrapper.eq(ResourceDO::getName, po.getName());
        if (resourceMapper.selectCount(wrapper) > 0) {
            throw new BizException(BizCodeEnum.RESOURCE_EXIT.getCode(), BizCodeEnum.RESOURCE_EXIT.getMsg());
        }
        // 合法数据入库
        ResourceDO resourceDO = new ResourceDO();
        try {
//            int a = 0;
//            a = 20/a;
            BeanUtils.copyProperties(po, resourceDO);
            resourceMapper.insert(resourceDO);
        } catch (Exception e) {
            log.info("新增资源失败");
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return resourceDO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResourceDO editResource(EditResourcePO po) {
        // 验证资源名是否重复
        LambdaQueryWrapper<ResourceDO> wrapper = new LambdaQueryWrapper();
        // 获取当前的资源名
        String resourceName = resourceMapper.selectById(po).getName();
        // 操作数存在校验
        if (StrUtil.isEmpty(resourceName)) {
            throw new BizException(BizCodeEnum.FIND_NO_ONE.getCode(), BizCodeEnum.FIND_NO_ONE.getMsg());
        }
        wrapper.eq(ResourceDO::getName, po.getName())
                .ne(ResourceDO::getName, resourceName);
        if (resourceMapper.selectCount(wrapper) > 0) {
            throw new BizException(BizCodeEnum.RESOURCE_EXIT.getCode(), BizCodeEnum.RESOURCE_EXIT.getMsg());
        }
        // 合法数据更新入库
        ResourceDO resourceDO = new ResourceDO();
        BeanUtils.copyProperties(po, resourceDO);
        resourceMapper.updateById(resourceDO);
        return resourceDO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResourceDO saveOrUpdateResource(SaveOrUpdateResourcePO saveOrUpdateResourcePO) {
        ResourceDO resourceDO = new ResourceDO();
        BeanUtils.copyProperties(saveOrUpdateResourcePO, resourceDO);
        // 验证资源名是否重复
        LambdaQueryWrapper<ResourceDO> wrapper = new LambdaQueryWrapper();
        wrapper.eq(ResourceDO::getName, resourceDO.getName());
        try {
            resourceService.saveOrUpdate(resourceDO);
        } catch (DuplicateKeyException e) {
            log.info("操作失败");
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new BizException(BizCodeEnum.RESOURCE_EXIT.getCode(), BizCodeEnum.RESOURCE_EXIT.getMsg());
        }
        return resourceDO;
    }

    @Override
    public Boolean grantUserRole(GrantUserRolePO rolePO) {
        List<UserRole> addUserRole = new ArrayList<>();
        List<UserRole> updateUserRole = new ArrayList<>();
        rolePO.getRoleDTOS().forEach(item->{
            if (ObjectUtil.isNull(item.getUserRoleId())) {
                UserRole userRole = new UserRole();
                userRole.setUserId(rolePO.getUserId());
                userRole.setRoleId(item.getRoleId());
                userRole.setEnable(1);
                addUserRole.add(userRole);
            }
            else {
                UserRole userRole = new UserRole();
                userRole.setId(item.getUserRoleId());
                userRole.setUserId(rolePO.getUserId());
                userRole.setRoleId(item.getRoleId());
                userRole.setEnable(item.getEnable());
                updateUserRole.add(userRole);
            }
        });
        if (ObjectUtil.isNotEmpty(addUserRole)) {
           this.saveBatch(addUserRole);
        }
        if (ObjectUtil.isNotEmpty(updateUserRole)) {
            this.updateBatchById(updateUserRole);
        }
        return true;
    }

    /**
     * 通过用户id 资源id获取用户资源信息
     *
     * @param userId
     * @param resourceId
     * @return
     */
//    private int findResource(Long userId, Long resourceId) {
//        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
//        wrapper.eq(UserRole::getUserId, userId)
//                .eq(UserRole::getResourceId, resourceId);
//        return this.count(wrapper);
//    }

}
